package com.yangxk.kadmin.web.module.system.service.impl;

import com.yangxk.kadmin.common.base.AbstractService;
import com.yangxk.kadmin.common.exception.BizException;
import com.yangxk.kadmin.common.exception.ParamException;
import com.yangxk.kadmin.common.support.BeanValidator;
import com.yangxk.kadmin.common.support.generator.IdGenerator;
import com.yangxk.kadmin.common.util.ValidUtil;
import com.yangxk.kadmin.web.common.Const;
import com.yangxk.kadmin.web.common.datascope.DataScope;
import com.yangxk.kadmin.web.common.enumeration.ResponseCode;
import com.yangxk.kadmin.web.module.system.form.DeptForm;
import com.yangxk.kadmin.web.module.system.mapper.DeptMapper;
import com.yangxk.kadmin.web.module.system.po.Dept;
import com.yangxk.kadmin.web.module.system.service.DeptService;
import com.yangxk.kadmin.web.module.system.vo.DeptTree;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class DeptServiceImpl extends AbstractService<Dept, Long> implements DeptService {

    @Autowired
    private DeptMapper deptMapper;

    @Override
    @DataScope(fieldName = "id")
    public List<DeptTree> queryDeptTree() {
        List<Dept> depts = deptMapper.queryAll();
        return transform2Tree(depts, Const.TREE_ROOT_PARENTID);
    }

    @Override
    @Transactional
    public long addDept(DeptForm deptForm) {
        BeanValidator.check(deptForm);
        Dept parentDept = deptMapper.selectByPrimaryKey(deptForm.getParentId());
        // 父节点被禁用, 不允许新增
        if (parentDept != null && Const.SYS_STATUS.DISABLE.equals(parentDept.getParentId())) {
            throw new BizException(ResponseCode.DEPT_DISABLED);
        }

        Dept dept = new Dept();

        BeanUtils.copyProperties(deptForm, dept);
        dept.setId(IdGenerator.getId());
        dept.setCreateTime(new Date());
        dept.setUpdateTime(new Date());
        dept.setPids(parentDept.getPids() + "," + parentDept.getId());

        deptMapper.insertSelective(dept);

        return dept.getId();
    }

    @Override
    @Transactional
    public void updateDept(DeptForm deptForm) {
        BeanValidator.check(deptForm);
        Dept parentDept = deptMapper.selectByPrimaryKey(deptForm.getParentId());
        if (parentDept == null)
            throw new BizException(ResponseCode.ILLEGAL_OPERATE);

        Dept before = deptMapper.selectByPrimaryKey(deptForm.getId());
        ValidUtil.checkNotNull(before, ResponseCode.UPDATE_CHECK_NULL.getMessage());

        Dept dept = new Dept();
        BeanUtils.copyProperties(deptForm, dept);
        dept.setUpdateTime(new Date());
        dept.setPids(parentDept.getPids() + "," + parentDept.getId());

        deptMapper.updateByPrimaryKeySelective(dept);
    }

    @Override
    @Transactional
    public void deleteDept(Long deptId) {
        Dept dept = deptMapper.selectByPrimaryKey(deptId);
        if (dept == null)
            throw new ParamException(ResponseCode.ILLEGAL_PARAM.getMessage());

        List<Dept> depts = recursiveQuery(deptId);

        Set<Long> ids = depts.stream().map(Dept::getId).collect(Collectors.toSet());
        ids.add(deptId);

        deptMapper.deleteMapper(new ArrayList<>(ids));
    }

    /**
     * 将List<Dept>转换为List<DeptTree>
     * create by yangxk on 2019/2/1 10:15
     */
    private List<DeptTree> transform2Tree(List<Dept> depts, long parentId) {
        List<DeptTree> result = new ArrayList<>();
        for (Dept dept : depts) {
            if (parentId == dept.getParentId()) {
                DeptTree vo = new DeptTree();
                BeanUtils.copyProperties(dept, vo);

                // 递归寻找子节点
                vo.setChildren(transform2Tree(depts, dept.getId()));

                result.add(vo);
            }
        }

        return result;
    }

    private List<Dept> recursiveQuery(long parentId) {
        List<Dept> result = new ArrayList<>();

        List<Dept> depts = deptMapper.queryByParentId(parentId);
        result.addAll(depts);
        if (!ValidUtil.isEmpty(depts)) {
            for (Dept dept : depts) {
                List<Dept> childs = recursiveQuery(dept.getId());
                result.addAll(childs);
            }
        }

        return result;
    }
}
